package fatboy.hypeerweb;

import java.util.List;
import java.util.PriorityQueue;
import java.util.Random;
import org.junit.Assert;
import org.junit.Test;

import fatboy.communication.ObjectID;

public class TestRemoveNode {
	private static final int LENGTH = 10;
	//private static final int FOUR = 4;
	private static final int THREE = 3;
	private static final int EIGHT = 8;
	
	public static void main(String[] args){
		Connection connect = new Connection();
		for(int i = 0 ; i < EIGHT;i++){
			connect.addNode(i);
		}
		List<Node> web = connect.getAllNodes();
		connect.removeNode(web.get(THREE));
		System.out.println(connect);
		//System.out.println(connect.getMyConnection());
	}
	/**
	 * Test the removal of a node
	 * Will test all possible permutations with 4 nodes
	 */
	@Test
	public void testRemove(){
		
		ObjectID.clearNumber();
		Connection connect = new Connection();
		
		//fill up hypeerweb
		for(int i = 0; i < EIGHT; i++){
			connect.addNode(i);
			//System.out.println("Test:/n" + connect + "\n=================\n");
		}
		
		List<Node> web = connect.getAllNodes();
		
		//System.out.println("PreResult :\n"+connect.toString());
		for(int i = 1; i < EIGHT; i++){
			connect.removeNode(connect.getAllNodes().get(web.size()-1));
		}
		
		Assert.assertTrue(connect.getAllNodes().size()==1);
		web = connect.getAllNodes();
		Assert.assertTrue(web.get(0).getAddress().getAddress()==0);
		
		//restore hypeer web back to the state as it was before deletion
		for(int i = 1; i < EIGHT; i++ ){
			connect.addNode(i);
		}
		//System.out.println("Intial :\n"+connect);
		web = connect.getAllNodes();
		connect.removeNode(web.get(1));
		//System.out.println("Step One :\n"+connect);
		
		connect.removeNode(web.get(1));
		//System.out.println("Step Two :\n"+connect);
		connect.removeNode(web.get(1));
		//System.out.println("Final Result :\n"+connect.toString());
		Assert.assertEquals(THREE , web.get(0).getNeighbors().size());

		//delete 0 node test
		connect.addNode(1);
		connect.addNode(2);
		web = connect.getAllNodes();
		connect.removeNode(web.get(0));
		Assert.assertEquals( 0, web.get(0).getAddress().getAddress());
		
	}
	
	private Random rand = new Random();
	
	/**
	 * Test if over large numbers of additions then removal if it crashes from 
	 * having pointers messed up, which it will if the pointers are messed up
	 */
	@Test
	public void scaleTest(){
		
			Connection connect = new Connection();
			int counter = 0;
			for(int i = 0; i < EIGHT; i++){
				//System.out.println("\n\n\n\n"+i + " run through");
				connect.addNode(counter++);
				System.out.println("adding");
				for(int j = 0 ; j < EIGHT*EIGHT; j++){
					
					connect.addNode(counter++);
				}
				System.out.println("removing");
				for(int j = 0; j < EIGHT*EIGHT; j++){
					
					int spot = rand.nextInt(connect.getAllNodes().size());
					//System.out.println("removing node at: " + spot);
					connect.removeNode(connect.getAllNodes().get(spot));
					//System.out.println(connect);
				}
			}
		
	}
	
	
	/**
	 * Tests to ensure that removeNeighbors works properly
	 */
	@Test
	public void testRemoveNeighbors(){
		Connection connect = new Connection();
		Node test = null;
		for(int i = 0; i < LENGTH; i++){
			test = connect.addNode(i);
		}
		PriorityQueue<Node> neighbors = test.getNeighbors();
		Node parent = test.getParent();
		
		test.removeNeighbors();
		
		for(Node n : neighbors){
			Assert.assertFalse(n.getNeighbors().contains(test));
			//System.out.println(n);
			if(n != parent){
				Assert.assertTrue(n.getPointers().contains(new SurrogatePointer(parent)));
				Assert.assertTrue(parent.getPointers().contains(new SurrogatePointer(n)));
			}
		}
		final int expectedChild = 5;
		Assert.assertFalse(parent.getChild().equals(test));
		Assert.assertEquals(new NodeAddress(expectedChild), parent.getChild().getAddress());
		
	}
	
	/**
	 * HypeerWeb integrity test check the consistency of updates of the node information:
	 *  states, folds, pointers, neighbors, children, parents, and data 
	 *  during the adds and removes of the last node.
	 * Assumed that add method handles node information correctly for all nodes and for
	 * 	arbitrary number of nodes in the HypeerWeb.
	 * 
	 * (Partial Condition Testing)
	 * 
	 * @author Ilya Vinogradov
	 * @date 26-Feb-10 6:52 p.m.
	 */
	@Test
	public void testHypeerWebIntegrity() {
		// Declaring hypeer web size
		final int SIZE = 33;
		
		// Declaring the array for hypeerweb expected node configurations
		String[] expectedNodeConfiguaration = new String[SIZE];
		
		Connection hypeerWeb = new Connection();
		
		
		// building the HypeerWeb and saving the node configurations
		for (int i = 0; i < SIZE ; i++ ) {
			hypeerWeb.addNode("Node #" + i);
			expectedNodeConfiguaration[i] = hypeerWeb.toString();
		}
		
		// verify last expected configuration
		Assert.assertEquals(expectedNodeConfiguaration[SIZE-1], hypeerWeb.toString());
		//System.out.println("=============\n" + expectedNodeConfiguaration[5]+ "\n===============\n");
		// get the list of nodes from the HypeerWeb and verify its size
		List<Node> web = hypeerWeb.getAllNodes();
		Assert.assertEquals(SIZE, web.size());
		
		// testing last node removal from the built HypeerWeb down to 0
		//Last node is not removed since hypeerweb is supposed to have at least 1 node
		for (int i = SIZE-1; i > 0 ; i-- ) {
			hypeerWeb.removeNode(web.get(i));
			Assert.assertEquals(expectedNodeConfiguaration[i-1], hypeerWeb.toString());
			
		}
		
	}
	
}


